package ch.subgate.spritestudio.tools;

import java.util.ArrayList;

import ch.subgate.spritestudio.constants.Constants;
import ch.subgate.spritestudio.types.PaintEvent;
import ch.subgate.spritestudio.types.Pixel;
import android.graphics.Bitmap;
import android.graphics.Color;

public class ImageProcessing {
	/** Method applies the Porter - Duff blending algorithm */
	public static int porterDuffOver(int src, int dst) {
		int res, ra, rr, rg, rb, sa, sr, sg, sb, da, dr, dg, db, max;
		//Set the maximum value for the attributes
		max = 0x000000ff;	//255
		
		//Get source attributes
		sa = (src & 0xff000000) >>> 24;
		sr = (src & 0x00ff0000) >> 16;
		sg = (src & 0x0000ff00) >> 8;
		sb = src & 0x000000ff;
		
		//Get destination attributes
		da = (dst & 0xff000000) >>> 24;
		dr = (dst & 0x00ff0000) >> 16;
		dg = (dst & 0x0000ff00) >> 8;
		db = dst & 0x000000ff;
		
		//Calculating the resulting color attributes
		ra = sa + (da - ((sa * da) / max));
		if (ra == 0) {
			rr = 0;
			rg = 0;
			rb = 0;
		}
		else {
			rr = (max / ra) * (((sa * sr) / max) + (((da * dr) / max) - ((sa * da * dr) / (max * max))));
			rg = (max / ra) * (((sa * sg) / max) + (((da * dg) / max) - ((sa * da * dg) / (max * max))));
			rb = (max / ra) * (((sa * sb) / max) + (((da * db) / max) - ((sa * da * db) / (max * max))));
		}
		
		res = Color.argb(ra, rr, rg, rb);
		return res;
	}
	
	/** Method changes colors brightness by var percent */
	public static int changeBrightness(int color, int var, boolean keepRel) {
		int a, r, g, b, d, res;
		a = (color & 0xff000000) >>> 24;
		r = (color & 0x00ff0000) >> 16;
		g = (color & 0x0000ff00) >> 8;
		b = color & 0x000000ff;
		if (var >= -100 && var <= 100) {
			if (keepRel) {
				r += r * var / 100;
				g += g * var / 100;
				b += b * var / 100;
			}
			else {
				d = 255 * var / 100;
				r += d;
				g += d;
				b += d;
			}
			if (r < 0) r = 0;
			if (r > 255) r = 255;
			if (g < 0) g = 0;
			if (g > 255) g = 255;
			if (b < 0) b = 0;
			if (b > 255) b = 255;
		}
		
		res = Color.argb(a, r, g, b);
		
		return res;
	}
	
	public static PaintEvent pencil(
			Bitmap image,
			int x, int y,
			int ncolor, int ocolor,
			PaintEvent event) {
		if (x >= 0 && x < image.getWidth() && y >= 0 && y < image.getHeight()) {
			if (event != null) {
				Pixel pixel = event.getLastPixel();
				if (pixel.mX == x && pixel.mY == y) {
					return event;
				}
			}
			else {
				event = new PaintEvent();
			}
			//Update the pixel color on the picture bitmap
			image.setPixel(x, y, ncolor);
			event.addPixel(new Pixel(x, y, ncolor, ocolor));
		}
		return event;
	}
	
	public static PaintEvent paintbucket(
			Bitmap image,
			int x, int y, int maxLeft, int maxRight,
			int color, int ncolor, int ocolor,
			PaintEvent event) {
		if (
				ocolor == color
				|| (color & Constants.COLOR_A_MASK) == 0
				|| x < 0
				|| x > image.getWidth() - 1
				|| y < 0
				|| y > image.getHeight() - 1
				|| maxLeft < 0
				|| maxRight > image.getWidth() - 1) {
			return null;
		}
		
		if (event != null) {
			event.recycle();
		}
		else {
			event = new PaintEvent();
		}
		
		Pixel pixel;
		ArrayList<Pixel> pixels = new ArrayList<Pixel>();
		pixels.add(new Pixel(x, y, ncolor, ocolor));
		
		while (!pixels.isEmpty()) {
			pixel = pixels.get(pixels.size() - 1);
			pixels.remove(pixels.size() - 1);
			if (pixel.mX >= maxLeft && pixel.mX < maxRight && pixel.mY >= 0 && pixel.mY < image.getHeight()) {
				if (image.getPixel(pixel.mX, pixel.mY) == ocolor) {
					image.setPixel(pixel.mX, pixel.mY, ncolor);
					event.addPixel(pixel);
					pixels.add(new Pixel(pixel.mX, pixel.mY - 1, ncolor, ocolor));
					pixels.add(new Pixel(pixel.mX, pixel.mY + 1, ncolor, ocolor));
					pixels.add(new Pixel(pixel.mX - 1, pixel.mY, ncolor, ocolor));
					pixels.add(new Pixel(pixel.mX + 1, pixel.mY, ncolor, ocolor));
				}
			}
			pixel = null;
		}
		return event;
	}
}
